<template>
  <div class="box">
    <div class="threebox" ref="threeContainer"></div>
  </div>
</template>

<script>
import * as THREE from "three";

export default {
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      fireworks: [],
      lastFireworkTime: 0,
    };
  },
  mounted() {
    this.initThree();
    window.addEventListener("resize", this.onWindowResize);
  },
  beforeDestroy() {
    window.removeEventListener("resize", this.onWindowResize);
    cancelAnimationFrame(this.animationFrameId);
    this.cleanup();
  },
  methods: {
    initThree() {
      // 初始化场景
      this.scene = new THREE.Scene();

      // 初始化相机
      this.camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
      this.camera.position.z = 50;

      // 初始化渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.setClearColor(0x000000);
      this.$refs.threeContainer.appendChild(this.renderer.domElement);

      // 开始动画循环
      this.animate();
    },

    createFirework(x, y) {
      const firework = {
        particles: [],
        geometry: new THREE.BufferGeometry(),
        material: new THREE.PointsMaterial({
          size: 0.3,
          vertexColors: true,
          blending: THREE.AdditiveBlending,
          transparent: true,
          opacity: 0.8,
        }),
        points: null,
      };

      // 初始化粒子
      for (let i = 0; i < 1000; i++) {
        const phi = Math.random() * Math.PI * 2; // 水平方向角度
        const theta = Math.random() * Math.PI; // 垂直方向角度
        const velocity = 2 + Math.random() * 2; // 随机速度

        const velocities = new THREE.Vector3(
          velocity * Math.sin(theta) * Math.cos(phi),
          velocity * Math.sin(theta) * Math.sin(phi),
          velocity * Math.cos(theta)
        );

        /* const velocity = new THREE.Vector3(
          (Math.random() - 0.5) * 4,
          (Math.random() - 0.5) * 4,
          (Math.random() - 0.5) * 4
        ); */

        firework.particles.push({
          position: new THREE.Vector3(x, y, 0),
          velocity: velocities,
          color: new THREE.Color(1, Math.random() * 0.2, Math.random() * 0.2),
          size: 0.3,
          life: 1.0,
        });
      }

      // 创建粒子系统
      this.updateFireworkGeometry(firework);
      firework.points = new THREE.Points(firework.geometry, firework.material);
      this.scene.add(firework.points);

      return firework;
    },

    updateFireworkGeometry(firework) {
      const positions = new Float32Array(firework.particles.length * 3);
      const colors = new Float32Array(firework.particles.length * 3);
      const sizes = new Float32Array(firework.particles.length);

      firework.particles.forEach((p, i) => {
        positions[i * 3] = p.position.x;
        positions[i * 3 + 1] = p.position.y;
        positions[i * 3 + 2] = p.position.z;

        colors[i * 3] = p.color.r;
        colors[i * 3 + 1] = p.color.g;
        colors[i * 3 + 2] = p.color.b;

        sizes[i] = p.size;
      });

      firework.geometry.setAttribute(
        "position",
        new THREE.BufferAttribute(positions, 3)
      );
      firework.geometry.setAttribute(
        "color",
        new THREE.BufferAttribute(colors, 3)
      );
      firework.geometry.setAttribute(
        "size",
        new THREE.BufferAttribute(sizes, 1)
      );
    },

    updateFirework(firework) {
      let alive = false;

      firework.particles.forEach((p) => {
        if (p.life > 0) {
          alive = true;
          p.position.add(p.velocity.clone().multiplyScalar(0.1));
          p.velocity.y -= 0.05; // 重力效果
          p.life -= 0.015;
          p.size = p.life * 0.3;
        }
      });

      if (alive) {
        this.updateFireworkGeometry(firework);
        firework.geometry.attributes.position.needsUpdate = true;
        firework.geometry.attributes.size.needsUpdate = true;
      }

      return alive;
    },

    animate(timestamp) {
      this.animationFrameId = requestAnimationFrame(this.animate);

      // 随机生成烟花（约每秒一个）
      if (timestamp - this.lastFireworkTime > 1000 && Math.random() < 0.3) {
        this.lastFireworkTime = timestamp;
        const x = (Math.random() - 0.5) * 60;
        const y = (Math.random() - 0.5) * 50;
        this.fireworks.push(this.createFirework(x, y));
      }

      // 更新所有烟花
      for (let i = this.fireworks.length - 1; i >= 0; i--) {
        const alive = this.updateFirework(this.fireworks[i]);
        if (!alive) {
          this.scene.remove(this.fireworks[i].points);
          this.fireworks[i].geometry.dispose();
          this.fireworks[i].material.dispose();
          this.fireworks.splice(i, 1);
        }
      }

      this.renderer.render(this.scene, this.camera);
    },

    onWindowResize() {
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
    },

    cleanup() {
      // 清理所有烟花资源
      this.fireworks.forEach((firework) => {
        this.scene.remove(firework.points);
        firework.geometry.dispose();
        firework.material.dispose();
      });
      this.fireworks = [];

      // 清理场景
      if (this.renderer) {
        this.renderer.dispose();
      }
    },
  },
};
</script>

<style lang="less" scoped>
.box {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #000;
  .threebox {
    height: 100%;
  }
}
</style>
